package com.axonactive.yolo.controller;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.ws.rs.GET;

import org.apache.log4j.Logger;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.axonactive.yolo.domain.Airline;
import com.axonactive.yolo.domain.Airport;
import com.axonactive.yolo.service.interfaces.AirlineService;
import com.axonactive.yolo.service.interfaces.AirportService;

@Controller
@RequestMapping(value = "/json")
public class JSONController {

	@Autowired
	AirlineService airlineService;

	@Autowired
	AirportService airportService;

	static List<Airport> cityList = new ArrayList<Airport>();
	static List<Airport> airportsList = new ArrayList<Airport>();

	private static final Logger LOGGER = Logger.getLogger(JSONController.class);

	@GET
	@RequestMapping(value = { "/airlinejson" })
	public @ResponseBody
	ModelAndView jsonAirline(
			@RequestParam(value = "queryParam") String queryParam) {
		try {
			List<Airline> airlineList = airlineService.searchByCode(queryParam,
					0);
			LOGGER.info(airlineList.toString());
			if (airlineList.isEmpty()) {
				airlineList = airlineService.searchByFirstCharacter(queryParam,
						0);
				if (airlineList.isEmpty()) {
					airlineList = airlineService.searchByToken(queryParam, 0);
				}
			}
			ObjectMapper mapper = new ObjectMapper();
			String a = mapper.writeValueAsString(airlineList);
			return new ModelAndView("json/airlinejson", "json", a);
		} catch (Exception e) {
			throw new RuntimeException("Error");
		}
	}

	@RequestMapping(value = { "/airport-json" }, method = RequestMethod.GET)
	public @ResponseBody
	ModelAndView jsonAirPort(
			@RequestParam(value = "queryParam") String queryParam)
			throws JsonGenerationException, JsonMappingException, IOException {
		List<Airport> returnAirportList = new ArrayList<Airport>();
		if(queryParam.length() <3){
			cityList = airportService.findByAppLocationType("City");
			airportsList = airportService.findByAppLocationType("Airport");
			returnAirportList = getAutoCompleteAirportByCityName(cityList,
					airportsList, queryParam, returnAirportList);
		}
		if (queryParam.length() == 3) {
			cityList = airportService.findByAppLocationType("City");
			airportsList = airportService.findByAppLocationType("Airport");
			returnAirportList = getAutoCompleteAirportByCityCode(cityList,
					airportsList, queryParam, returnAirportList);
			if (returnAirportList.size() < 10) {
				for (int i = 0; i < airportsList.size(); i++) {
					if (airportsList.get(i).getAirportCode()
							.equalsIgnoreCase(queryParam)) {
						addAirportToListByAirportCode(returnAirportList,
								airportsList.get(i), airportsList, queryParam);
					}
				}
			}
			if (returnAirportList.size() < 10) {
				returnAirportList = getAutoCompleteAirportByCityName(cityList,
						airportsList, queryParam, returnAirportList);
			}
		} else if (queryParam.length() > 3) {
			cityList = airportService.findByAppLocationType("City");
			airportsList = airportService.findByAppLocationType("Airport");
			returnAirportList = getAutoCompleteAirportByCityName(cityList,
					airportsList, queryParam, returnAirportList);
		}
		ObjectMapper mapper = new ObjectMapper();
		String jsonAirportList = mapper.writeValueAsString(returnAirportList);
		return new ModelAndView("json/airportjson", "json", jsonAirportList);
	}

	private List<Airport> getAutoCompleteAirportByCityCode(
			List<Airport> cityList, List<Airport> airportsList,
			String queryParam, List<Airport> returnAirportList) {
		for (int i = 0; i < cityList.size(); i++) {
			if (cityList.get(i).getCityCode().equalsIgnoreCase(queryParam)) {
				if (returnAirportList.size() < 10) {
					boolean cont = true;
					for (int k = 0; k < returnAirportList.size(); k++) {
						if (compareTwoAirport(returnAirportList.get(k),
								cityList.get(i))) {
							cont = false;
							break;
						}
					}
					if (cont) {
						returnAirportList.add(cityList.get(i));
						String cityCode = cityList.get(i).getCityCode();
						for (int j = 0; j < airportsList.size(); j++) {
							if (airportsList.get(j).getCityCode()
									.equalsIgnoreCase(cityCode)) {
								airportsList.get(j).setBlankSpace(
										"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");
								returnAirportList.add(airportsList.get(j));
							}
						}
					}
				}
			}
		}
		return returnAirportList;
	}

	private List<Airport> getCityBelongToAirport(List<Airport> cityList,
			List<Airport> airportsList, String queryParam,
			List<Airport> returnAirportList, String cityCode) {
		for (int i = 0; i < cityList.size(); i++) {
			if (cityList.get(i).getCityCode().equals(cityCode)) {
				boolean cont = checkExistAirportInList(returnAirportList,
						cityList.get(i));
				if (cont) {
					addAirportToListByCityCode(returnAirportList,
							cityList.get(i), airportsList);
				}
			}
		}
		return returnAirportList;
	}

	public List<Airport> getAutoCompleteAirportByCityName(
			List<Airport> cityList, List<Airport> airportsList,
			String queryParam, List<Airport> returnAirportList) {
		for (int i = 0; i < cityList.size(); i++) {
			if (cityList.get(i).getCityName().toLowerCase()
					.contains(queryParam.toLowerCase())) {
				if (returnAirportList.size() < 10) {
					boolean cont = checkExistAirportInList(returnAirportList,
							cityList.get(i));
					if (cont) {
						addAirportToListByCityCode(returnAirportList,
								cityList.get(i), airportsList);
					}
				}
			}
		}
		if (returnAirportList.size() < 10) {
			for (int i = 0; i < airportsList.size(); i++) {
				if (airportsList.get(i).getAirportName().toLowerCase()
						.contains(queryParam.toLowerCase())) {
					boolean cont = checkExistAirportInList(returnAirportList,
							cityList.get(i));
					if (cont) {
						addAirportToListByAirportCode(returnAirportList,
								airportsList.get(i), airportsList, queryParam);
					}
				}
			}

		}
		return returnAirportList;
	}

	public void addAirportToListByAirportCode(List<Airport> returnAirportList,
			Airport airport, List<Airport> airportsList, String queryParam) {
		boolean exist = true;
		String cityCode = airport.getCityCode();
		for (int j = 0; j < cityList.size(); j++) {
			if (cityList.get(j).getCityCode().equals(cityCode)) {
				returnAirportList = getCityBelongToAirport(cityList,
						airportsList, queryParam, returnAirportList, cityCode);
				exist = false;
			}
		}
		if (exist) {
			returnAirportList.add(airport);
		}
	}

	public void addAirportToListByCityCode(List<Airport> returnAirportList,
			Airport airport, List<Airport> airportsList) {
		returnAirportList.add(airport);
		String cityCode = airport.getCityCode();
		for (int j = 0; j < airportsList.size(); j++) {
			if (airportsList.get(j).getCityCode().equals(cityCode)) {
				airportsList.get(j).setBlankSpace(
						"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");
				returnAirportList.add(airportsList.get(j));
			}
		}
	}

	public boolean checkExistAirportInList(List<Airport> returnAirportList,
			Airport airport) {
		for (int k = 0; k < returnAirportList.size(); k++) {
			if (compareTwoAirport(returnAirportList.get(k), airport)) {
				return false;
			}
		}
		return true;
	}

	public boolean compareTwoAirport(Airport airport, Airport target) {
		if (airport.getAppLocationType().equals(target.getAppLocationType())
				&& airport.getCityCode().equals(target.getCityCode())
				&& airport.getCityName().equals(target.getCityName())) {
			return true;
		}
		return false;
	}

}
